package mi.payment.admin;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;
import android.widget.Toast;

import com.sunmi.pay.hardware.aidlv2.AidlConstantsV2;
import com.sunmi.pay.hardware.aidlv2.bean.ApduRecvV2;
import com.sunmi.pay.hardware.aidlv2.bean.ApduSendV2;
import com.sunmi.pay.hardware.aidlv2.security.SecurityOptV2;

import java.security.MessageDigest;
import java.util.Random;

import lainey.ui.utils.LogUtil;
import lainey.ui.utils.SharedPreferencesUtil;
import mi.payment.Constant;
import mi.payment.MyApplication;
import mi.payment.R;
import mi.payment.bean.db.TradeData;
import mi.payment.constants.Params;
import mi.payment.db.dao.PayDetail;
import mi.payment.ui.base.ParentActivity;
import mi.payment.utils.AllianceUtil;
import mi.payment.utils.AsciiUtil;
import mi.payment.utils.ByteUtil;
import mi.payment.utils.EncryptUtil;
import mi.payment.utils.transaction.RKITask;
import sunmi.payment.ui.dialog.LoadDialog;

public class RKI {

    private String pin = "250707";
    private String acquireID = "abmB".toUpperCase();
    private String vendorID = "iPay88".toUpperCase();

    public static String counter = "212121212344";

    public static String mSessionKey;
    public static String mSessionKcv;
    public static String mSessionAppID;
    public static String mEncryptedData;

    private String mRndB1B2;
    private byte[] mIAKBytes;
    private byte[] mTSKBytes;
    private byte[] mAppKeyBytes;
    private byte[] mRndA1B2B1A2Bytes;

    private ParentActivity mActivity;
    private SecurityOptV2 mSecurityOptV2;

    private static final String KID = "key_tle_key_id";

    private static void saveTleKid(String kid) {
        SharedPreferences preferences = MyApplication.getInstance().getSharedPreferences(SharedPreferencesUtil.PREFERENCE_FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = preferences.edit();
        editor.putString(KID, kid);
        editor.apply();
    }

    public static String getTleKid() {
        SharedPreferences preferences = MyApplication.getInstance().getSharedPreferences(SharedPreferencesUtil.PREFERENCE_FILE_NAME,
                Context.MODE_PRIVATE);
        return preferences.getString(KID, "");
    }

    RKI(ParentActivity activity) {
        mActivity = activity;
        mSecurityOptV2 = MyApplication.getInstance().mSecurityOptV2;
    }

    void operate() {
        try {
            mActivity.showLoadingDialog();

            boolean result = selectAID();
            if (result == false) {
                mActivity.dismissLoadingDialog();
                return;
            }

            result = establishSecureChannel();
            if (result == false) {
                mActivity.dismissLoadingDialog();
                return;
            }

            result = getAppKey();
            if (result == false) {
                mActivity.dismissLoadingDialog();
                return;
            }

            result = initializeMutualAuthentication();
            if (result == false) {
                mActivity.dismissLoadingDialog();
                return;
            }

            result = mutualAuthentication();
            if (result == false) {
                mActivity.dismissLoadingDialog();
                return;
            }

            result = verifyPIN();
            if (result == false) {
                mActivity.dismissLoadingDialog();
                return;
            }

            result = requestSession();
            if (result == false) {
                mActivity.dismissLoadingDialog();
                return;
            }

            parametersDownload();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @SuppressLint("StaticFieldLeak")
    private void parametersDownload() {
        RKITask task = new RKITask(mActivity) {

            @Override
            protected void onPostExecuteImpl(TradeData tradeData) {
                PayDetail resPay = tradeData.getPayDetail();
                boolean equals = TextUtils.equals("00", resPay.tradeAnswerCode);
                if (equals) {
                    try {
                        mEncryptedData = mEncryptedData.substring(20);
                        equals = authSession(mEncryptedData);
                        if (equals) {
                            Toast.makeText(mActivity, R.string.merchant_safe_code_success, Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(mActivity, R.string.merchant_safe_code_failed, Toast.LENGTH_SHORT).show();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

        };
        TradeData tradeData = Params.newTradeData();
        LoadDialog loadDialog = mActivity.getLoadingDialog(R.string.load_downloading);
        task.setLoadDialog(loadDialog);
        task.execute(tradeData);
    }

    private boolean selectAID() throws Exception {
        ApduSendV2 send = new ApduSendV2();
        send.command = ByteUtil.hexStr2Bytes("00A4040C");
        send.lc = Short.parseShort("7");
        send.le = Short.parseShort("255");
        send.dataIn = ByteUtil.hexStr2Bytes("A0000047530501");

        ApduRecvV2 rec = sendCommand(send);
        String swa = ByteUtil.byte2HexStr(rec.swa);
        return TextUtils.equals("90", swa);
    }

    /**
     * 建立安全通道
     */
    private boolean establishSecureChannel() throws Exception {
        ApduSendV2 send = new ApduSendV2();
        send.command = ByteUtil.hexStr2Bytes("00450002");
        send.lc = Short.parseShort("16");
        send.le = Short.parseShort("255");

        String rndX = generateRandom(8);
        LogUtil.e(Constant.TAG, "rndX: " + rndX);

        String cryptogramX = getEstablishSecureChannelData(rndX);

        send.dataIn = ByteUtil.hexStr2Bytes(rndX + cryptogramX);
        ApduRecvV2 rec = sendCommand(send);
        if (rec.outlen > 0) {
            String temp = ByteUtil.bytes2HexStr(rec.outData).substring(0, rec.outlen * 2);
            String eTSK = temp.substring(0, 32);
            String eTSK_kcv = temp.substring(32, 36);
            LogUtil.e(Constant.TAG, "eTSK: " + eTSK);
            LogUtil.e(Constant.TAG, "TSK_kcv: " + eTSK_kcv);

            byte[] eTSK_bytes = ByteUtil.hexStr2Bytes(eTSK);
            mTSKBytes = EncryptUtil.encrypt3Des(mIAKBytes, eTSK_bytes);
            String TSK = ByteUtil.bytes2HexStr(mTSKBytes);
            LogUtil.e(Constant.TAG, "TSK: " + TSK);

            byte[] data = new byte[8];
            byte[] calcKCV_bytes = EncryptUtil.encrypt3Des(mTSKBytes, data);
            String calcKCV = ByteUtil.bytes2HexStr(calcKCV_bytes).substring(0, 4);
            LogUtil.e(Constant.TAG, "calc kcv: " + calcKCV);

            return TextUtils.equals(eTSK_kcv, calcKCV);
        }
        return false;
    }

    /**
     * 获取App Key
     */
    private boolean getAppKey() throws Exception {
        ApduSendV2 send = new ApduSendV2();
        send.command = ByteUtil.hexStr2Bytes("00460000");
        ApduRecvV2 rec = sendCommand(send);
        if (rec.outlen > 0) {
            String temp = ByteUtil.bytes2HexStr(rec.outData).substring(0, rec.outlen * 2);
            String eAppKey = temp.substring(0, 48);
            String eAppKey_kcv = temp.substring(48, 52);
            LogUtil.e(Constant.TAG, "eAppKey: " + eAppKey);
            LogUtil.e(Constant.TAG, "appKey_kcv: " + eAppKey_kcv);

            eAppKey = eAppKey.substring(0, 32);
            byte[] data = ByteUtil.hexStr2Bytes(eAppKey);
            mAppKeyBytes = EncryptUtil.decrypt3Des(mTSKBytes, data);
            String appKey = ByteUtil.bytes2HexStr(mAppKeyBytes);
            LogUtil.e(Constant.TAG, "appKey: " + appKey);

            data = new byte[8];
            byte[] calcKCV_bytes = EncryptUtil.encrypt3Des(mAppKeyBytes, data);
            String calcKCV = ByteUtil.bytes2HexStr(calcKCV_bytes).substring(0, 4);
            LogUtil.e(Constant.TAG, "calc kcv: " + calcKCV);

            return TextUtils.equals(eAppKey_kcv, calcKCV);
        }
        return false;
    }

    /**
     * 初始化双向认证通道
     */
    private boolean initializeMutualAuthentication() throws Exception {
        ApduSendV2 send = new ApduSendV2();
        send.command = ByteUtil.hexStr2Bytes("00430000");
        send.lc = Short.parseShort("8");
        send.le = Short.parseShort("255");

        String rndA1A2 = generateRandom(8);
        LogUtil.e(Constant.TAG, "rndA1A2: " + rndA1A2);

        byte[] data = ByteUtil.hexStr2Bytes(rndA1A2);
        byte[] eRndA1A2_bytes = EncryptUtil.encrypt3Des(mAppKeyBytes, data);
        String eRndA1A2 = ByteUtil.bytes2HexStr(eRndA1A2_bytes);
        LogUtil.e(Constant.TAG, "eRndA1A2: " + eRndA1A2);

        send.dataIn = eRndA1A2_bytes;
        ApduRecvV2 rec = sendCommand(send);
        if (rec.outlen > 0) {
            String temp = ByteUtil.bytes2HexStr(rec.outData).substring(0, rec.outlen * 2);
            String eRndA1B2B1A2 = temp.substring(0, 32);
            LogUtil.e(Constant.TAG, "eRndA1B2B1A2: " + eRndA1B2B1A2);

            // Notice encrypt
            mRndA1B2B1A2Bytes = EncryptUtil.encrypt3Des(mAppKeyBytes, rec.outData);
            String rndA1B2B1A2 = ByteUtil.bytes2HexStr(mRndA1B2B1A2Bytes);
            LogUtil.e(Constant.TAG, "rndA1B2B1A2: " + rndA1B2B1A2);

            String recRndA1A2 = rndA1B2B1A2.substring(0, 8) + rndA1B2B1A2.substring(24, 32);
            LogUtil.e(Constant.TAG, "recRndA1A2: " + recRndA1A2);

            mRndB1B2 = rndA1B2B1A2.substring(16, 24) + rndA1B2B1A2.substring(8, 16);
            LogUtil.e(Constant.TAG, "rndB1B2: " + mRndB1B2);

            return TextUtils.equals(rndA1A2, recRndA1A2);
        }
        return false;
    }

    /**
     * 相互认证
     */
    private boolean mutualAuthentication() throws Exception {
        ApduSendV2 send = new ApduSendV2();
        send.command = ByteUtil.hexStr2Bytes("00440000");
        send.lc = Short.parseShort("8");
        send.le = Short.parseShort("255");

        byte[] data = ByteUtil.hexStr2Bytes(mRndB1B2);
        byte[] eRndB1B2_bytes = EncryptUtil.encrypt3Des(mAppKeyBytes, data);
        String eRndB1B2 = ByteUtil.bytes2HexStr(eRndB1B2_bytes);
        LogUtil.e(Constant.TAG, "eRndB1B2: " + eRndB1B2);

        send.dataIn = eRndB1B2_bytes;

        ApduRecvV2 rec = sendCommand(send);
        LogUtil.e(Constant.TAG, "相互认证: " + rec.outlen);
        String swa = ByteUtil.byte2HexStr(rec.swa);
        return TextUtils.equals("90", swa);
    }

    /**
     * 校验PIN
     */
    private boolean verifyPIN() throws Exception {
        ApduSendV2 send = new ApduSendV2();
        send.command = ByteUtil.hexStr2Bytes("00200000");
        send.lc = Short.parseShort("8");
        send.le = Short.parseShort("255");

        byte[] pin_bytes = pin.getBytes();
        String pin = ByteUtil.bytes2HexStr(pin_bytes);
        LogUtil.e(Constant.TAG, "pin: " + pin);

        byte[] data = new byte[8];
        System.arraycopy(pin_bytes, 0, data, 0, pin_bytes.length);
        data[6] = (byte) 0x80;
        data[7] = (byte) 0x00;
        byte[] ePin_bytes = EncryptUtil.encrypt3Des(mRndA1B2B1A2Bytes, data);
        String ePin = ByteUtil.bytes2HexStr(ePin_bytes);
        LogUtil.e(Constant.TAG, "ePin: " + ePin);

        send.dataIn = ePin_bytes;

        ApduRecvV2 rec = sendCommand(send);
        LogUtil.e(Constant.TAG, "校验PIN: " + rec.outlen);
        String swa = ByteUtil.byte2HexStr(rec.swa);
        return TextUtils.equals("90", swa);
    }

    /**
     * 请求会话
     */
    private boolean requestSession() throws Exception {
        ApduSendV2 send = new ApduSendV2();
        send.command = ByteUtil.hexStr2Bytes("00410000");
        send.lc = Short.parseShort("40");
        send.le = Short.parseShort("255");

        byte[] dataIn = new byte[40];

        byte[] bytes = acquireID.getBytes();
        System.arraycopy(bytes, 0, dataIn, 0, bytes.length);

        bytes = vendorID.getBytes();
        System.arraycopy(bytes, 0, dataIn, 20, bytes.length);

        String requestData = ByteUtil.bytes2HexStr(dataIn);
        LogUtil.e(Constant.TAG, "requestData: " + requestData);

        send.dataIn = dataIn;

        ApduRecvV2 rec = sendCommand(send);
        if (rec.outlen > 0) {
            byte[] data = new byte[20];
            System.arraycopy(rec.outData, 0, data, 0, 20);
            mSessionAppID = ByteUtil.bytes2HexStr(data);
            LogUtil.e(Constant.TAG, "sessionAppID: " + mSessionAppID);

            data = new byte[16];
            System.arraycopy(rec.outData, 20, data, 0, 16);
            mSessionKey = ByteUtil.bytes2HexStr(data);
            LogUtil.e(Constant.TAG, "sessionKey: " + mSessionKey);

            data = new byte[2];
            System.arraycopy(rec.outData, 36, data, 0, 2);
            mSessionKcv = ByteUtil.bytes2HexStr(data);
            LogUtil.e(Constant.TAG, "sessionKcv: " + mSessionKcv);
        }

        String swa = ByteUtil.byte2HexStr(rec.swa);
        return TextUtils.equals("90", swa);
    }

    /**
     * 会话认证
     */
    private boolean authSession(String hexData) throws Exception {
        ApduSendV2 send = new ApduSendV2();
        send.command = ByteUtil.hexStr2Bytes("00420000");
        send.lc = Short.parseShort(hexData.length() / 2 + "");
        send.le = Short.parseShort("255");

        LogUtil.e(Constant.TAG, "authSession: " + hexData);
        send.dataIn = ByteUtil.hexStr2Bytes(hexData);

        ApduRecvV2 rec = sendCommand(send);
        if (rec.outlen > 0) {
            String temp = ByteUtil.bytes2HexStr(rec.outData).substring(0, rec.outlen * 2);
            temp = AllianceUtil.decode250(temp);
            LogUtil.e(Constant.TAG, "Keys: " + temp);

            ///////////////////////////////////////////////////////////////////////////////////////
            /////////////////////////// TODO RKI KEY //////////////////////////////////////////////
            ///////////////////////////////////////////////////////////////////////////////////////
            String rki_kid = temp.substring(0, 12);
            LogUtil.e(Constant.TAG, "rki_kid: " + rki_kid);

            String separator = temp.substring(12, 14);
            LogUtil.e(Constant.TAG, "separator: " + separator);

            String rki_dek = temp.substring(14, 46);
            LogUtil.e(Constant.TAG, "rki_dek: " + rki_dek);

            byte[] RKI_DEK = ByteUtil.hexStr2Bytes(rki_dek);    // RKI_DEK

            separator = temp.substring(46, 48);
            LogUtil.e(Constant.TAG, "separator: " + separator);

            String rki_dek_kcv = temp.substring(48, 56);
            LogUtil.e(Constant.TAG, "rki_dek_kcv: " + rki_dek_kcv);
            rki_dek_kcv = AsciiUtil.asciiToString(rki_dek_kcv);
            LogUtil.e(Constant.TAG, "rki_dek_kcv: " + rki_dek_kcv);

            byte[] RKI_DEK_KCV = ByteUtil.hexStr2Bytes(rki_dek_kcv);    // RKI_DEK KCV

            byte[] data = new byte[8];
            byte[] calcKCV_bytes = EncryptUtil.encrypt3Des(RKI_DEK, data);
            String calcKCV = ByteUtil.bytes2HexStr(calcKCV_bytes).substring(0, 4);
            LogUtil.e(Constant.TAG, "calc kcv: " + calcKCV);

            separator = temp.substring(56, 58);
            LogUtil.e(Constant.TAG, "separator: " + separator);

            String rki_mek = temp.substring(58, 90);
            LogUtil.e(Constant.TAG, "rki_mek: " + rki_mek);

            byte[] RKI_MEK = ByteUtil.hexStr2Bytes(rki_mek);    // RKI_MEK

            separator = temp.substring(90, 92);
            LogUtil.e(Constant.TAG, "separator: " + separator);

            String rki_mek_kcv = temp.substring(92, 100);
            LogUtil.e(Constant.TAG, "rki_mek_kcv: " + rki_mek_kcv);
            rki_mek_kcv = AsciiUtil.asciiToString(rki_mek_kcv);
            LogUtil.e(Constant.TAG, "rki_mek_kcv: " + rki_mek_kcv);

            byte[] RKI_MEK_KCV = ByteUtil.hexStr2Bytes(rki_mek_kcv);    // RKI_MEK KCV

            data = new byte[8];
            calcKCV_bytes = EncryptUtil.encrypt3Des(RKI_MEK, data);
            calcKCV = ByteUtil.bytes2HexStr(calcKCV_bytes).substring(0, 4);
            LogUtil.e(Constant.TAG, "calc kcv: " + calcKCV);

            separator = temp.substring(100, 102);
            LogUtil.e(Constant.TAG, "separator: " + separator);
            ///////////////////////////////////////////////////////////////////////////////////////
            ///////////////////////////////////////////////////////////////////////////////////////


            ///////////////////////////////////////////////////////////////////////////////////////
            //////////////////// TODO TLE KEY /////////////////////////////////////////////////////
            ///////////////////////////////////////////////////////////////////////////////////////
            String tle_kid = temp.substring(102, 114);
            LogUtil.e(Constant.TAG, "tle_kid: " + tle_kid);

            separator = temp.substring(114, 116);
            LogUtil.e(Constant.TAG, "separator: " + separator);

            String tle_dek = temp.substring(116, 148);
            LogUtil.e(Constant.TAG, "tle_dek: " + tle_dek);

            byte[] TLE_DEK = ByteUtil.hexStr2Bytes(tle_dek);    // TLE_DEK

            separator = temp.substring(148, 150);
            LogUtil.e(Constant.TAG, "separator: " + separator);

            String tle_dek_kcv = temp.substring(150, 158);
            LogUtil.e(Constant.TAG, "tle_dek_kcv: " + tle_dek_kcv);

            tle_dek_kcv = AsciiUtil.asciiToString(tle_dek_kcv);
            LogUtil.e(Constant.TAG, "tle_dek_kcv: " + tle_dek_kcv);

            byte[] TLE_DEK_KCV = ByteUtil.hexStr2Bytes(tle_dek_kcv);    // TLE_DEK KCV

            data = new byte[8];
            calcKCV_bytes = EncryptUtil.encrypt3Des(TLE_DEK, data);
            calcKCV = ByteUtil.bytes2HexStr(calcKCV_bytes).substring(0, 4);
            LogUtil.e(Constant.TAG, "calc kcv: " + calcKCV);

            // Save TLE_DEK
            int result = mSecurityOptV2.savePlaintextKey(AidlConstantsV2.Security.KEY_TYPE_REC, TLE_DEK,
                    TLE_DEK_KCV, AidlConstantsV2.Security.KEY_ALG_TYPE_3DES, Constant.indexRootDEK);
            LogUtil.e(Constant.TAG, "Save TLE_DEK result: " + result);

            saveTleKid(tle_kid);

            String appID = "3031";
            String generateKeyStr = counter + tle_kid + appID;
            byte[] generateKeyBytes = ByteUtil.hexStr2Bytes(generateKeyStr);

            byte[] generateDataBytes = new byte[16];
            System.arraycopy(generateKeyBytes, 0, generateDataBytes, 0, generateKeyBytes.length);

            String generateData = ByteUtil.bytes2HexStr(generateDataBytes);
            LogUtil.e(Constant.TAG, "generateData: " + generateData);


            byte[] ENCRYPT_TLE_DEK = EncryptUtil.encrypt3Des(TLE_DEK, generateDataBytes);
            String encrypt_tle_dek = ByteUtil.bytes2HexStr(ENCRYPT_TLE_DEK);
            LogUtil.e(Constant.TAG, "encrypt_tle_dek: " + encrypt_tle_dek);

            // Save ENCRYPT_TLE_DEK
            result = mSecurityOptV2.savePlaintextKey(AidlConstantsV2.Security.KEY_TYPE_REC, ENCRYPT_TLE_DEK, null,
                    AidlConstantsV2.Security.KEY_ALG_TYPE_3DES, Constant.indexDEK);
            LogUtil.e(Constant.TAG, "Save encrypt_TLE_DEK result: " + result);

            ///////////////////////////////////////////////////////////////////////////////////////
            ///////////////////////////////////////////////////////////////////////////////////////

            separator = temp.substring(158, 160);
            LogUtil.e(Constant.TAG, "separator: " + separator);

            String tle_mek = temp.substring(160, 192);
            LogUtil.e(Constant.TAG, "tle_mek: " + tle_mek);

            byte[] TLE_MEK = ByteUtil.hexStr2Bytes(tle_mek);    // TLE_MEK

            separator = temp.substring(192, 194);
            LogUtil.e(Constant.TAG, "separator: " + separator);

            String tle_mek_kcv = temp.substring(194, 202);
            LogUtil.e(Constant.TAG, "tle_mek_kcv: " + tle_mek_kcv);

            tle_mek_kcv = AsciiUtil.asciiToString(tle_mek_kcv);
            LogUtil.e(Constant.TAG, "tle_mek_kcv: " + tle_mek_kcv);

            byte[] TLE_MEK_KCV = ByteUtil.hexStr2Bytes(tle_mek_kcv);    //TLE_DEK KCV

            data = new byte[8];
            calcKCV_bytes = EncryptUtil.encrypt3Des(TLE_MEK, data);
            calcKCV = ByteUtil.bytes2HexStr(calcKCV_bytes).substring(0, 4);
            LogUtil.e(Constant.TAG, "calc kcv: " + calcKCV);

            // Save TLE_MEK
            result = mSecurityOptV2.savePlaintextKey(AidlConstantsV2.Security.KEY_TYPE_MAK, TLE_MEK,
                    TLE_MEK_KCV, AidlConstantsV2.Security.KEY_ALG_TYPE_3DES, Constant.indexRootMAK);
            LogUtil.e(Constant.TAG, "Save TLE_MEK result: " + result);

            byte[] ENCRYPT_TLE_MEK = EncryptUtil.encrypt3Des(TLE_MEK, generateDataBytes);
            String encrypt_tle_mek = ByteUtil.bytes2HexStr(ENCRYPT_TLE_MEK);
            LogUtil.e(Constant.TAG, "encrypt_tle_mek: " + encrypt_tle_mek);

            // Save ENCRYPT_TLE_MEK
            result = mSecurityOptV2.savePlaintextKey(AidlConstantsV2.Security.KEY_TYPE_MAK, ENCRYPT_TLE_MEK, null,
                    AidlConstantsV2.Security.KEY_ALG_TYPE_3DES, Constant.indexMAK);
            LogUtil.e(Constant.TAG, "Save ENCRYPT_TLE_MEK result: " + result);
        }

        String swa = ByteUtil.byte2HexStr(rec.swa);
        return TextUtils.equals("90", swa);
    }

    private String generateRandom(int num) {
        String result = "";
        for (int i = 0; i < num; i++) {
            int var = new Random().nextInt(9);
            result += "3" + var;
        }
        return result;
    }

    private String getEstablishSecureChannelData(String rndX) throws Exception {
        byte[] acquireIdBytes = new byte[20];
        byte[] bytes = acquireID.getBytes();
        System.arraycopy(bytes, 0, acquireIdBytes, 0, bytes.length);

        String acquireId = ByteUtil.bytes2HexStr(acquireIdBytes);
        LogUtil.e(Constant.TAG, "acquireId: " + acquireId);

        byte[] vendorIdBytes = new byte[20];
        bytes = vendorID.getBytes();
        System.arraycopy(bytes, 0, vendorIdBytes, 0, bytes.length);

        String vendorId = ByteUtil.bytes2HexStr(vendorIdBytes);
        LogUtil.e(Constant.TAG, "vendorId: " + vendorId);

        byte[] rnd_x_bytes = ByteUtil.hexStr2Bytes(rndX);

        byte[] blockA = new byte[10];
        System.arraycopy(acquireIdBytes, 0, blockA, 0, 10);
        String temp = ByteUtil.bytes2HexStr(blockA);
        LogUtil.e(Constant.TAG, "blockA: " + temp);

        byte[] blockB = new byte[10];
        System.arraycopy(acquireIdBytes, 10, blockB, 0, 10);
        temp = ByteUtil.bytes2HexStr(blockB);
        LogUtil.e(Constant.TAG, "blockB: " + temp);

        byte[] blockC = new byte[10];
        System.arraycopy(vendorIdBytes, 0, blockC, 0, 10);
        temp = ByteUtil.bytes2HexStr(blockC);
        LogUtil.e(Constant.TAG, "blockC: " + temp);

        byte[] blockD = new byte[10];
        System.arraycopy(vendorIdBytes, 10, blockD, 0, 10);
        temp = ByteUtil.bytes2HexStr(blockD);
        LogUtil.e(Constant.TAG, "blockD: " + temp);

        byte[] blockAD = new byte[blockA.length];
        for (int i = 0; i < blockA.length; i++) {
            int var = blockA[i] ^ blockD[i];
            blockAD[i] = (byte) var;
        }
        temp = ByteUtil.bytes2HexStr(blockAD);
        LogUtil.e(Constant.TAG, "blockAD: " + temp);

        byte[] blockBC = new byte[blockB.length];
        for (int i = 0; i < blockB.length; i++) {
            int var = blockB[i] ^ blockC[i];
            blockBC[i] = (byte) var;
        }
        temp = ByteUtil.bytes2HexStr(blockBC);
        LogUtil.e(Constant.TAG, "blockBC: " + temp);

        byte[] blockADBC = new byte[blockAD.length + blockBC.length];
        System.arraycopy(blockAD, 0, blockADBC, 0, blockAD.length);
        System.arraycopy(blockBC, 0, blockADBC, blockAD.length, blockBC.length);
        temp = ByteUtil.bytes2HexStr(blockADBC);
        LogUtil.e(Constant.TAG, "blockADBC: " + temp);

        byte[] blockF = new byte[blockADBC.length];
        System.arraycopy(rnd_x_bytes, 0, blockF, 0, rnd_x_bytes.length);
        for (int i = 0; i < blockF.length; i++) {
            blockF[i] ^= blockADBC[i];
        }
        temp = ByteUtil.bytes2HexStr(blockF);
        LogUtil.e(Constant.TAG, "blockF: " + temp);

        MessageDigest digest = MessageDigest.getInstance("SHA-1");
        digest.update(blockF);
        byte[] blockG = digest.digest();
        temp = ByteUtil.bytes2HexStr(blockG);
        LogUtil.e(Constant.TAG, "blockG: " + temp);

        mIAKBytes = new byte[16];
        System.arraycopy(blockG, 0, mIAKBytes, 0, 16);
        temp = ByteUtil.bytes2HexStr(mIAKBytes);
        LogUtil.e(Constant.TAG, "IAK: " + temp);

        byte[] cryptogramX = EncryptUtil.encrypt3Des(mIAKBytes, rnd_x_bytes);
        temp = ByteUtil.bytes2HexStr(cryptogramX);
        LogUtil.e(Constant.TAG, "cryptogramX: " + temp);
        return temp;
    }

    private ApduRecvV2 sendCommand(ApduSendV2 send) throws Exception {
        ApduRecvV2 rec = new ApduRecvV2();
        int result = MyApplication.getInstance().mReadCardOptV2.apduCommand(AidlConstantsV2.CardType.IC.getValue(), send, rec);
        if (result == 0) {
            String temp = "SWA：" + ByteUtil.byte2HexStr(rec.swa);
            temp += " SWB：" + ByteUtil.byte2HexStr(rec.swb);
            if (rec.outlen > 0) {
                temp += " outData：" + ByteUtil.bytes2HexStr(rec.outData).substring(0, rec.outlen * 2);
            } else {
                temp += " outData：";
            }
            LogUtil.e(Constant.TAG, "rec: " + temp);
        }
        return rec;
    }


}
